package stage;

import fileoperation.FileDeletion;
import gitobject.Blob;
import repository.Repository;

import java.io.*;
import java.util.Date;
import java.util.LinkedList;

/**
 * 暂存区类，使用 LinkedList 数据结构，包括以下方法：
 * readIndex - 从index文件中读取存储的暂存区文件存入 indexList 对象
 * writeIndex - 将 indexList 中的对象写入 index 文件
 * addItem/deleteItem - 向 indexList 对象中增加、删除文件
 * inIndex - 比较（从工作区根目录起始的）文件名检查暂存区是否已存在同名文件
 * clearStage - 删除index文件中的内容
 */
public class Index {
    private LinkedList<String[]> indexList = new LinkedList<>();
    private static String indexFilePath = Repository.getGitDir() + File.separator + "index";

    /**
     * Constructor. Load the files into indexList.
     * @throws IOException
     */
    public Index() throws IOException {
        indexList = readIndex();
    }

    public LinkedList<String[]> getIndexList() {
        return indexList;
    }

    /**
     * Load the blob items from `.jit/index` file into a linked list
     * @throws IOException
     * @return LinkedList<String[]> list
     */
    private LinkedList<String[]> readIndex() throws IOException {
//        File indexFile = new File(indexFilePath);
        File indexFile = new File(Repository.getGitDir() + File.separator + "index");
        if (indexFile.exists()) {
            FileInputStream is = new FileInputStream(indexFile);
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            LinkedList<String[]> blobList = new LinkedList<String[]>();
            // read line by line and separate info of each blob into a String[]
            try{
                String line = br.readLine();
                while (line != null){
                    String[] arr = line.split(" ");
                    blobList.add(arr);
                    line = br.readLine();
                }
            }
            catch (IOException e){
                e.printStackTrace();
            }
            finally {
                br.close();
                is.close();
            }

            return blobList;
        }
        else {
            throw new IOException("Index file doesn't exists. Please run 'jit init' first.");
        }
    }

    /**
     * Write blob items to `.jit/index`
     * @throws IOException
     */
    public void writeIndex() throws IOException {
        File indexFile = new File(indexFilePath);
        if(indexFile.exists()) {
            FileWriter fw = new FileWriter(indexFile);
            for(String[] arr : indexList) {
                String str = String.join(" ", arr);
                fw.write(str);
                fw.write("\n");
            }
            fw.flush();
            fw.close();
        }
    }

    /**
     * Add a file into indexList.
     * @param file
     * @throws Exception
     */
    public void addItem(File file) throws Exception {
        String[] record = new String[3];
        Blob blob = new Blob(file);
        String workDir = Repository.getWorkTree();
        String fileName = file.getPath().substring(workDir.length() + 1); // filename starting from workDir

        long time = file.lastModified();
        String timeStr = String.valueOf(time);
//        String timeStamp = new Date(file.lastModified()).toString();

        record[0] = blob.getKey();
        record[1] = fileName;
        record[2] = timeStr;
        indexList.add(record);

        //Save file(blob object) into '.jit/objects'
        blob.compressWrite();
    }

    /**
     * Delete a file from indexList.
     * @param file
     */
    public void deleteItem(File file) {
        int idx = inIndex(file);
        if(idx != -1) indexList.remove(idx);
    }

    /**
     * Check if a file already exists in indexList.
     * @param file
     * @throws Exception
     */
    public int inIndex(File file) {
        String workDir = Repository.getWorkTree();
        String fileName = file.getPath().substring(workDir.length() + 1); // filename starting from workDir
        for(int i = 0; i < indexList.size(); i++) {
            if(indexList.get(i)[1].equals(fileName)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Delete the content of index file to clear stage.
     */
    public static void clearStage() {
        File file = new File(indexFilePath);
        FileDeletion.deleteContent(file);
    }
}
